package com.rede.paylib;

import android.app.Activity;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.Log;

import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingFlowParams;
import com.android.billingclient.api.ConsumeResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsParams;
import com.android.billingclient.api.SkuDetailsResponseListener;

import java.util.ArrayList;
import java.util.List;

/**
 * GooglePay 购买商品流程
 * @author zhengxh on 2018/9/11
 * @version 1.0
 */
public class GooglePayManager {
    private final String TAG = "GooglePayManager";
    private static GooglePayManager instances;
    private BillingClient mBillingClient;
    private OnPayListener payListener;
    private GooglePayManager(){}

    public static GooglePayManager get() {
        if(instances==null){
            synchronized (GooglePayManager.class){
                if(instances==null)instances = new GooglePayManager();
            }
        }
        return instances;
    }

    /**
     * 初始化客户端
     * @param context
     * @return
     */
    public GooglePayManager init(Context context){
        if(mBillingClient==null){
            mBillingClient = BillingClient.newBuilder(context.getApplicationContext()).setListener(purchasesUpdatedListener).build();
        }
        return this;
    }

    /**
     * 注册支付监听器
     * @param listener
     */
    public void setOnPayListener(OnPayListener listener){
        this.payListener = payListener;
    }

    /**
     * 购买应用内商品
     * @param activity
     * @param orderId 唯一的商品ID
     */
    public void buy(Activity activity,  String orderId){
        purchase(activity, orderId, BillingClient.SkuType.INAPP);
    }

    /**
     * 消耗商品
     * @param productToken 商品token
     */
    public void consumeAsync(final String productToken) {
        // Creating a runnable from the request to use it inside our connection retry policy below
        Runnable consumeRequest = new Runnable() {
            @Override
            public void run() {
                // Consume the purchase async
                mBillingClient.consumeAsync(productToken, consumeResponseListener);
            }
        };
        executeServiceRequest(consumeRequest);
    }

    /**
     * 查询商品详情
     * @param productIds 商品唯一id列表
     * @param listener
     */
    public void queryProductDetail(ArrayList<String> productIds, ProducDetailsListener listener){
        querySkuDetailsAsync(productIds, BillingClient.SkuType.INAPP, listener);
    }


    //购买/订阅商品
    private void purchase(final Activity activity, final String skuId,final String skuType){
        Runnable purchaseFlowRequest = new Runnable() {
            @Override
            public void run() {
                log(">>>>purchase>>>>>skuType:"+skuType+"; skuId:"+skuId);
                BillingFlowParams purchaseParams = BillingFlowParams.newBuilder()
                        .setSku(skuId).setType(skuType).build();
                mBillingClient.launchBillingFlow(activity, purchaseParams);
            }
        };
        executeServiceRequest(purchaseFlowRequest);
    }

    /**
     * 查询已经购买未消费的商品列表
     */
    public void queryPurchases(final QueryProducListener listener) {
        Runnable queryToExecute = new Runnable() {
            @Override
            public void run() {
                Purchase.PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.INAPP);
                if(purchasesResult!=null && purchasesResult.getResponseCode()== BillingClient.BillingResponse.OK){
                    List<Purchase> purchases =  purchasesResult.getPurchasesList();
                    ArrayList<Product> list = new ArrayList<>();
                    if(purchases!=null&&!purchases.isEmpty()){
                        for(Purchase purchase:purchases){
                            list.add(new Product(purchase.getSku(), purchase.getPurchaseToken()));
                        }
                    }
                    if(listener!=null){
                        listener.onProducList(list);
                    }
                }
            }
        };
        executeServiceRequest(queryToExecute);
    }

    //===========================================相关业务===========================================================

    //连接服务器
    private void startServiceConnection(final Runnable executeOnSuccess) {
        mBillingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(@BillingClient.BillingResponse int billingResponseCode) {
                Log.d(TAG, "Setup finished. Response code: " + billingResponseCode);
                log("连接服务完成==========Response code："+billingResponseCode);
                if (billingResponseCode == BillingClient.BillingResponse.OK) {
                    if (executeOnSuccess != null) {
                        executeOnSuccess.run();
                    }
                }else{
                    if(payListener!=null){
                        payListener.onFail("connected fial");
                    }
                }
            }

            @Override
            public void onBillingServiceDisconnected() {
                log("连接务器失败");
                if(payListener!=null){
                    payListener.onFail("connected fial");
                }
            }
        });
    }

    //消耗商品回调
    private ConsumeResponseListener consumeResponseListener = new ConsumeResponseListener(){
        @Override
        public void onConsumeResponse(int responseCode, String purchaseToken) {
            log("======消耗商品回调====responseCode:"+responseCode+"; purchaseToken:"+purchaseToken);
            if(payListener!=null){
                payListener.onConsumeFinished(purchaseToken);
            }
        }
    };


    //购买商品回调接口
    private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener(){
        @Override
        public void onPurchasesUpdated(int responseCode, @Nullable List<Purchase> purchases) {
            log("======接收到购买回调====responseCode:"+responseCode+"; purchases:"+purchases);
            if(responseCode== BillingClient.BillingResponse.OK&&purchases!=null){
                ArrayList<Product> list = new ArrayList<>();
                //消耗商品
                for(Purchase purchase:purchases){
                    list.add(new Product(purchase.getSku(), purchase.getPurchaseToken()));
                }
                if(payListener!=null)payListener.onPurchasesFinished(list);
            }else{
                if(payListener!=null)payListener.onPurchasesFinished(null);
            }
        }
    };



    private void querySkuDetailsAsync(final ArrayList<String> productIds, final String skuType, final ProducDetailsListener listener) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
                params.setSkusList(productIds).setType(skuType);
                mBillingClient.querySkuDetailsAsync(params.build(),new SkuDetailsResponseListener() {
                    @Override
                    public void onSkuDetailsResponse(int responseCode, List<SkuDetails> skuDetailsList) {
                        log("======查询购买产品详情====responseCode:"+responseCode+"; skuDetailsList:"+skuDetailsList);
                        List<String> skuList = new ArrayList<>();
                        for (SkuDetails detail : skuDetailsList){
                            skuList.add(detail.toString());
                        }
                        listener.onProducDetails(skuList);
                    }
                });
            }
        };
        executeServiceRequest(runnable);
    }

    private void executeServiceRequest(Runnable runnable) {
        if(mBillingClient.isReady()){
            runnable.run();
        } else {
            // If billing service was disconnected, we try to reconnect 1 time.
            // (feel free to introduce your retry policy here).
            startServiceConnection(runnable);
        }
    }

    private void log(String msg){
        Log.i(TAG, ">>>>>>>>>>"+msg);
    }

}
